package com.winchain.chainbill.bill.biz.send.cmd;

import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.invoince.po.InvBas;
import com.shell.bee.invoince.po.InvBasHist;
import com.shell.bee.invoince.po.InvRel;
import com.shell.bee.invoince.po.InvUseStats;
import com.shell.bee.invoince.service.InvBasHistService;
import com.shell.bee.invoince.service.InvBasService;
import com.shell.bee.invoince.service.InvRelService;
import com.shell.bee.invoince.service.InvUseStatsService;
import com.shell.framework.command.CallbackContext;
import com.shell.framework.command.CommandContext;
import com.shell.framework.command.ICallback;
import com.shell.framework.command.ICommand;
import com.shell.framework.utils.CommonDataUtil;
import com.winchain.chainbill.bill.base.po.CbAtt;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.biz.Bill;
import com.winchain.chainbill.bill.biz.send.vo.BillAttInvoice;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class BillInvoiceCmd<T> implements ICommand<Bill<T>>, ICallback<Bill<T>, AcctTxRec> {
	@Autowired
	private InvBasService invBasService;
	@Autowired
	private InvRelService invRelService;
	@Autowired
	private InvUseStatsService invUseStatsService;
	@Autowired
	private InvBasHistService invBasHistService;

	public boolean callback(CallbackContext<Bill<T>, AcctTxRec> context) throws Exception {
		execute(context);
		return false;
	}

	public boolean execute(CommandContext<Bill<T>> context) throws Exception {
		String invType = context.getStringValue("invType");
		String str = "����";
		BigDecimal billAmt = BigDecimal.ZERO;
		if ("2".equals(invType)) {
			CbRec record = ((Bill) context.getSource()).getRec();
			billAmt = record.getBillAmt();
		} else if ("3".equals(invType)) {
			Bill<T> tBill = (Bill) context.getSource();
			CbXfe xfe = (CbXfe) tBill.getSource();
			if (xfe == null) {
				xfe = (CbXfe) context.getValue("billSource");
			}
			if (xfe != null) {
				billAmt = xfe.getBillAmt();
			}
			str = "����";
		} else if ("4".equals(invType)) {
			Bill<T> tBill = (Bill) context.getSource();
			CbDct dct = (CbDct) tBill.getSource();
			if (dct == null) {
				dct = (CbDct) context.getValue("billSource");
			}
			if (dct != null) {
				billAmt = dct.getDctAmt();
			}
			str = "����";
		}
		Object rejectFlag = context.getValue("rejectFlag");

		Object delAtts = context.getValue("delAtts");
		if (delAtts != null) {
			List<CbAtt> delCbAtts = (List) delAtts;
			for (CbAtt delCbAtt : delCbAtts) {
				this.invBasService.deleteAndUpdateInv(delCbAtt.getAttId(), invType);
			}
		}
		Object saveAtts = context.getValue("saveAtts");
		BillAttInvoice attInvoice;
		BigDecimal balanceBillAmt;
		if (saveAtts != null) {
			Object saveCbAtts = (List) saveAtts;

			BigDecimal balance = BigDecimal.ZERO;

			StringBuilder histSb = new StringBuilder();
			for (Iterator localIterator2 = ((List) saveCbAtts).iterator(); localIterator2.hasNext();) {
				attInvoice = (BillAttInvoice) localIterator2.next();
				InvUseStats invUseStats = this.invUseStatsService.selectOneByCodeAndNo(attInvoice.getInvCode(),
						attInvoice.getInvNo());
				if ((rejectFlag != null) && (((Boolean) rejectFlag).booleanValue()) && (invUseStats != null)) {
					InvRel invRel = this.invRelService.selectOneByBizId(attInvoice.getAttId(), invType);
					BigDecimal beforeBalance = invUseStats.getInvAmt().subtract(invUseStats.getUseAmt());
					if (invRel != null) {
						beforeBalance = invUseStats.getInvAmt().subtract(invUseStats.getUseAmt())
								.add(invRel.getUseAmt());
					}
					balance = balance.add(beforeBalance);
				} else if (invUseStats != null) {
					BigDecimal afterBalance = invUseStats.getInvAmt().subtract(invUseStats.getUseAmt());
					balance = balance.add(afterBalance);
					InvBasHist invBasHist = this.invBasHistService.selectOneByCodeAndNo(attInvoice.getInvCode(),
							attInvoice.getInvNo());
					if ((invBasHist != null) && (invBasHist.getState().equals("1"))) {
						histSb.append(attInvoice.getInvCode()).append(":").append(attInvoice.getInvNo()).append(",");
					}
				} else {
					BigDecimal invAmt = transferInvAmt(attInvoice.getInvAmt());
					balance = balance.add(invAmt);
				}
			}
			if (billAmt.compareTo(balance) > 0) {
				throw new UnCheckMsgException("����������������������" + str + "����������������������");
			}
			if ((histSb != null) && (histSb.length() > 0)) {
				String histStr = histSb.substring(0, histSb.length() - 1);
				throw new UnCheckMsgException("��������" + histStr + "����������");
			}
			balanceBillAmt = billAmt;
			for (BillAttInvoice attInvoice2 : (List<BillAttInvoice>) saveCbAtts) {
				InvBas invBas = new InvBas();
				BeanUtils.copyProperties(attInvoice2, invBas);
				invBas.setInvAmt(transferInvAmt(attInvoice2.getInvAmt()));
				invBas.setTax(transferInvAmt(attInvoice2.getTax()));
				invBas.setTaxRate(transferTaxRate(attInvoice2.getTaxRate()));
				balanceBillAmt = this.invBasService.saveAndUpdateInvBasInfo(attInvoice2.getAttId(), invBas, invType,
						balanceBillAmt, CommonDataUtil.getUserId());
			}
		}
		return false;
	}

	private BigDecimal transferInvAmt(String amt) {
		String ramt = amt;
		if (StringUtil.notEmpty(ramt)) {
			ramt = ramt.replace("��", "").replace("��", "").replace("$", "");
		}
		if (!StringUtil.emptyAndNull(ramt)) {
			return new BigDecimal(ramt.trim());
		}
		return null;
	}

	private BigDecimal transferTaxRate(String taxRate) {
		if ((StringUtil.notEmpty(taxRate)) && (taxRate.indexOf("%") >= 0)) {
			String rate = taxRate.replace("%", "").trim();
			if (StringUtil.emptyAndNull(rate)) {
				return null;
			}
			return new BigDecimal(rate).divide(new BigDecimal("100"), 2, 4);
		}
		if (StringUtil.notEmpty(taxRate)) {
			return new BigDecimal(taxRate.trim());
		}
		return null;
	}
}
